package com.heima.leetcode.practice;

import java.util.HashMap;

/**
 * 罗马数转为整数 13
 * @author 勾新杰
 * @version 1.0
 * @date 2024/10/22 18:09
 */
public class E13 {

    private static HashMap<Character, Integer> map = new HashMap<>(); // 存储罗马数字对应权重的哈希表

    //static代码块，对static变量进行初始化，在类加载时执行
    static {
        map.put('I', 1);
        map.put('V', 5);
        map.put('X', 10);
        map.put('L', 50);
        map.put('C', 100);
        map.put('D', 500);
        map.put('M', 1000);
    }

    /**
     * <h3>方法一 用hashMap</h3>
     * @param s 字符串
     * @return 罗马数字转化为数字
     */
    public int romanToInt1(String s) {
        HashMap<Character, Integer> romanMap = createRomanMap();
        char[] array = s.toCharArray();
        int result = 0;
        char lastChar = ' ';
        for (char c : array) {
            result += romanMap.get(c);
            if (c == 'V' || c == 'X' ){
                if (lastChar == 'I') {
                    result -= 2;
                }
            } else if (c == 'L' || c == 'C') {
                if (lastChar == 'X'){
                    result -= 20;
                }
            } else if (c == 'D' || c == 'M') {
                if (lastChar == 'C'){
                    result -= 200;
                }
            }
            lastChar = c;
        }
        return result;
    }

    /**
     * <h3>方法二 用hashMap，对方法一代码的简化</h3>
     * @param s 罗马数字字符串
     * @return 转换结果
     */
    public int romanToInt2(String s) {
        HashMap<Character, Integer> romanMap = createRomanMap();
        char[] array = s.toCharArray();
        int result = 0;
        for (int i = 0; i < array.length; i++) {
            Integer current = romanMap.get(array[i]);
            // 只有那六种特殊情况，小的才会出现在大的前面，这时候减去小的就可以了
            if (i + 1 < array.length && current < romanMap.get(array[i + 1])){
                result -= current;
            }else {
                result += current;
            }
        }
        return result;
    }

    /**
     * <h3>方法三，在以上基础上用静态变量加速哈希表的初始化</h3>
     * @param s 罗马数字字符串
     * @return 转换结果
     */
    public int romanToInt3(String s) {
        char[] array = s.toCharArray();
        int result = 0;
        for (int i = 0; i < array.length; i++) {
            Integer current = map.get(array[i]);
            // 只有那六种特殊情况，小的才会出现在大的前面，这时候减去小的就可以了
            if (i + 1 < array.length && current < map.get(array[i + 1])){
                result -= current;
            }else {
                result += current;
            }
        }
        return result;
    }

    /**
     * <h3>方法四，用switch语句</h3>
     * @param s 罗马数字字符串
     * @return 返回转换结果
     */
    public int romanToInt4(String s) {
        char[] array = s.toCharArray();
        int result = 0;
        for (int i = 0; i < array.length; i++) {
                int currentValue = getValue(array[i]);
                if (i + 1 < array.length && currentValue < getValue(array[i + 1])) {
                    result -= currentValue;
                }else {
                    result += currentValue;
                }
        }
        return result;
    }

    /**
     * 存储罗马数字对应权重的哈希表
     * @return 哈希表
     */
    private HashMap<Character, Integer> createRomanMap(){
        HashMap<Character, Integer> map = new HashMap<>();
        map.put('I', 1);
        map.put('V', 5);
        map.put('X', 10);
        map.put('L', 50);
        map.put('C', 100);
        map.put('D', 500);
        map.put('M', 1000);
        return map;
    }

    /**
     * 将指定罗马字符转成数字
     * @param c 字符
     * @return 转成数字
     */
    private int getValue(char c){
        return switch (c) {
            case 'I' -> 1;
            case 'V' -> 5;
            case 'X' -> 10;
            case 'L' -> 50;
            case 'C' -> 100;
            case 'D' -> 500;
            case 'M' -> 1000;
            default -> throw new IllegalArgumentException("非法字符");
        };
    }
}
